00001 /*! \file 00002 * X-Forge Util <br> 00003 * Copyright 2000-2003 Fathammer Ltd 00004 * 00005 * \brief Primitive bitmap font printer class. 00006 * Needs some work (create instead of init; gl sprites instead 00007 * of the glsurface drawing currently in use. 00008 * 00009 * $Id: XFuPrinter.cpp,v 1.29 2003/06/25 09:59:34 lars Exp $ 00010 * $Date: 2003/06/25 09:59:34 $ 00011 * $Revision: 1.29 $ 00012 */ 00013 00014 #include <stdlib.h> 00015 #include <xfcore/XFcCore.h> 00016 #include <xfutil/XFuPrinter.h> 00017 #include <xfcore/XFcPixelConverter.h> 00018 00019 #define TORGB16(r,g,b) (unsigned short)(((((r) >> 3) & 0x1f) << 11) | ((((g) >> 3) & 0x1f) << 6) | ((((b) >> 3) & 0x1f))) 00020 00021 XFuPrinter * XFuPrinter::create(const CHAR *aFname) 00022 { 00023 return create(aFname,0,REALi(1),REALi(1)); 00024 } 00025 00026 XFuPrinter * XFuPrinter::create(const CHAR *aFname, INT32 aAlphamask) 00027 { 00028 return create(aFname,aAlphamask,REALi(1),REALi(1)); 00029 } 00030 00031 XFuPrinter * XFuPrinter::create(const CHAR *aFname, INT32 aAlphamask, REAL aXScale, REAL aYScale) 00032 { 00033 INT32 wid, ht; 00034 UINT8 *pal; 00035 UINT16 *pal16; 00036 UINT8 *pic; 00037 INT32 i; 00038 INT paletted; 00039 00040 UINT16 alphamask = (UINT16)(XFCPC_X888_TO_55X5(aAlphamask)); 00041 00042 XFcImageLoader::loadImageInfo(aFname, &wid, &ht, NULL, &paletted); 00043 00044 if (!paletted) return NULL; // TODO: create non-paletted version too 00045 if (wid == 0) return NULL; 00046 00047 XFcImageLoader::loadImagePaletted(aFname, &pal, &pic); 00048 if (pal == NULL || pic == NULL) 00049 { 00050 delete[] pic; 00051 delete[] pal; 00052 return NULL; 00053 } 00054 00055 pal16 = new UINT16[256]; 00056 for (i = 0; i < 256; ++i) 00057 pal16[i] = TORGB16(pal[i * 3 + 0], pal[i * 3 + 1], pal[i * 3 + 2]); 00058 00059 XFuPrinter *p = new XFuPrinter(); 00060 00061 p->mLetterSpacing = 2; // default letter spacing 00062 00063 p->mMaxletter = ht / wid; 00064 p->mLetter = new XFcGLSurface *[p->mMaxletter]; 00065 for (i = 0; i < p->mMaxletter; ++i) 00066 { 00067 INT32 j, l; 00068 int letterofs = i * wid * wid; 00069 INT32 ls = wid, rs = 0; 00070 for (j = 0, l = 0; j < wid; ++j) 00071 { 00072 INT32 k; 00073 for (k = 0; k < wid; ++k, ++l) 00074 { 00075 int c = pal16[pic[letterofs + l] & 0xff]; 00076 if (c == alphamask) 00077 { 00078 } 00079 else 00080 { 00081 if (rs < k) rs = k; 00082 if (ls > k) ls = k; 00083 } 00084 } 00085 } 00086 int charwid = rs - ls + 1; 00087 if (charwid < 0) 00088 { 00089 charwid = 0; // empty character 00090 p->mLetter[i] = NULL; 00091 } 00092 else 00093 { 00094 XFcGLSurface *tSurface; 00095 tSurface = XFcGLSurface::create(charwid, wid); 00096 short *fb; 00097 tSurface->lock((void **)&fb); 00098 rs = wid - charwid; 00099 int m = 0, k; 00100 for (j = 0, l = ls; j < wid; ++j, l += rs) 00101 { 00102 for (k = 0; k < charwid; ++k,++l,++m) 00103 { 00104 int c = pal16[pic[letterofs + l] & 0xff]; 00105 fb[m] = (INT16)c; 00106 } 00107 } 00108 tSurface->unlock(); 00109 00110 if (aXScale != REALi(1) || aYScale != REALi(1)) 00111 { 00112 INT32 w = (INT32)(aXScale * (REAL)charwid); 00113 INT32 h = (INT32)(aYScale * (REAL)wid); 00114 XFcGLSurface *tSurface2 = XFcGLSurface::create(w,h); 00115 if (tSurface2) 00116 { 00117 tSurface2->drawImage(tSurface,0,0,w,h); 00118 delete tSurface; 00119 tSurface = tSurface2; 00120 } 00121 } 00122 00123 p->mLetter[i] = tSurface; 00124 p->mLetter[i]->setColorKey(aAlphamask); 00125 p->mLetter[i]->enableColorKey(1); 00126 } 00127 } 00128 00129 p->mLineSpacing = (INT32)(aXScale * (REAL)wid); 00130 p->mLineHeight = (INT32)(aYScale * (REAL)wid); 00131 00132 if (p->mLetter['0' - 33]) 00133 p->mSpaceWidth = p->mLetter['0' - 33]->getWidth() / 2; 00134 else 00135 p->mSpaceWidth = p->mLineHeight / 2; 00136 00137 delete[] pic; 00138 delete[] pal; 00139 delete[] pal16; 00140 return p; 00141 00142 } 00143 00144 00145 INT32 XFuPrinter::print(XFcGLSurface *aTarget, XFcRectangle *aTargetRect, const CHAR *aText, 00146 INT32 aBlendType, INT32 aBlendValue, XFcRectangle *aClipRect) 00147 { 00148 XFCASSERT(aTarget); 00149 00150 XFcRectangle rect; 00151 00152 if (aTargetRect == NULL) 00153 { 00154 rect.mX = 0; 00155 rect.mY = 0; 00156 rect.mWidth = aTarget->getWidth(); 00157 rect.mHeight = aTarget->getHeight(); 00158 } 00159 else 00160 { 00161 rect = *aTargetRect; 00162 } 00163 00164 // Find longest word 00165 INT32 i, j, longest = 0; 00166 i = 0; 00167 j = 0; 00168 while (aText[i] != 0) 00169 { 00170 i++; 00171 j++; 00172 if (aText[i] == ' ') 00173 { 00174 if (longest < j) 00175 longest = j; 00176 j = 0; 00177 } 00178 } 00179 00180 if (longest < j) 00181 longest = j; 00182 00183 CHAR * temp = new CHAR[longest + 1]; 00184 00185 if (temp == NULL) 00186 return 0; 00187 00188 INT32 ofsx, ofsy; 00189 ofsx = rect.mX; 00190 ofsy = rect.mY; 00191 i = 0; 00192 do 00193 { 00194 if (aText[i] == ' ') 00195 { 00196 // Only advance cursor if not at the start of line. 00197 if (ofsx != rect.mX) 00198 { 00199 ofsx += mSpaceWidth + mLetterSpacing; 00200 } 00201 i++; 00202 } 00203 else if (aText[i] == '\n') 00204 { 00205 ofsx = rect.mX; 00206 ofsy += mLineSpacing; 00207 i++; 00208 } 00209 else 00210 { 00211 j = 0; 00212 while (aText[i] != 0 && aText[i] != ' ' && aText[i] != '\n') 00213 { 00214 temp[j] = aText[i]; 00215 i++; 00216 j++; 00217 } 00218 temp[j] = 0; 00219 00220 INT32 tx, ty; 00221 stringMetrics(temp, tx, ty); 00222 00223 if (tx + ofsx > (rect.mX + rect.mWidth) && ofsx != rect.mX) 00224 { 00225 ofsx = rect.mX; 00226 ofsy += mLineSpacing; 00227 } 00228 00229 print(aTarget, ofsx, ofsy, temp, aBlendType, aBlendValue, aClipRect); 00230 00231 ofsx += tx; 00232 } 00233 00234 } 00235 while (aText[i] != 0); 00236 00237 delete[] temp; 00238 00239 return ofsy - rect.mY + mLineHeight; 00240 } 00241 00242 00243 void XFuPrinter::print(XFcGLSurface *aTarget, INT32 aX, INT32 aY, const CHAR *aText, 00244 INT32 aBlendType, INT32 aBlendValue, XFcRectangle *aClipRect) 00245 { 00246 if ((aTarget != NULL) && (aText != NULL)) 00247 { 00248 unsigned char *p = (unsigned char *)aText; 00249 int xo = 0; 00250 INT32 i; 00251 00252 INT32 yMax = 0, xMax = 0; 00253 INT32 h = mLineHeight; 00254 00255 if (aClipRect) 00256 { 00257 yMax = aClipRect->mY + aClipRect->mHeight; 00258 xMax = aClipRect->mX + aClipRect->mWidth; 00259 } 00260 00261 while (*p) 00262 { 00263 if (*p == 32) 00264 { 00265 xo += mSpaceWidth + mLetterSpacing; 00266 } 00267 else 00268 { 00269 if (*p == '\n') 00270 { 00271 xo = 0; 00272 aY += mLineSpacing; 00273 } 00274 else 00275 { 00276 i = ((UINT8)*p) - 33; 00277 if (i >= 0 && i < mMaxletter) 00278 { 00279 if (mLetter[i] != NULL) 00280 { 00281 INT32 w = mLetter[i]->getWidth(); 00282 INT32 xp = aX + xo; 00283 if (aClipRect == NULL) 00284 { 00285 aTarget->drawImageBlend( 00286 mLetter[i], xp, aY, 00287 aBlendType, aBlendValue); 00288 } 00289 else 00290 { 00291 XFcRectangle srcRect; 00292 srcRect.mX = aClipRect->mX - xp; 00293 srcRect.mY = aClipRect->mY - aY; 00294 INT32 endX = xMax - xp; 00295 INT32 endY = yMax - aY; 00296 00297 if (srcRect.mX < w && endX >= 0 && 00298 srcRect.mY < h && endY >= 0) 00299 { 00300 if (srcRect.mX < 0) srcRect.mX = 0; 00301 if (srcRect.mY < 0) srcRect.mY = 0; 00302 if (endX > w) endX = w; 00303 if (endY > h) endY = h; 00304 srcRect.mWidth = endX - srcRect.mX; 00305 srcRect.mHeight = endY - srcRect.mY; 00306 aTarget->drawImageBlend( 00307 mLetter[i], xp + srcRect.mX, aY + srcRect.mY, srcRect, 00308 aBlendType, aBlendValue); 00309 } 00310 } 00311 xo += w; 00312 } 00313 xo += mLetterSpacing; 00314 } 00315 } 00316 } 00317 ++p; 00318 } 00319 } 00320 } 00321 00322 00323 void XFuPrinter::stringMetrics(const CHAR *aText, INT32 &aWidth, INT32 &aHeight) 00324 { 00325 if (this == NULL) return; 00326 unsigned char *p = (unsigned char *)aText; 00327 int xo = 0, y = 0; 00328 int maxx = 0; 00329 INT32 i; 00330 while (*p) 00331 { 00332 if (*p == 32) 00333 { 00334 xo += mSpaceWidth; 00335 if (maxx < xo) maxx = xo; 00336 xo += mLetterSpacing; 00337 } 00338 else 00339 { 00340 if (*p == '\n') 00341 { 00342 xo = 0; 00343 y += mLineSpacing; 00344 } 00345 else 00346 { 00347 i = ((UINT8)*p) - 33; 00348 if ( i >= 0 && i < mMaxletter ) 00349 { 00350 if (mLetter[i]) 00351 xo += mLetter[i]->getWidth(); 00352 if (maxx < xo) maxx = xo; 00353 xo += mLetterSpacing; 00354 } 00355 } 00356 } 00357 00358 ++p; 00359 00360 } 00361 y += mLineHeight; 00362 aHeight = y; 00363 aWidth = maxx; 00364 } 00365 00366 00367 INT32 XFuPrinter:: getCharWidth(CHAR aChar) 00368 { 00369 INT32 i = (INT32)(((UINT8)aChar) - 33); 00370 if (aChar == 32) 00371 return mSpaceWidth; 00372 else if (i < 0 || i >= mMaxletter || mLetter[i] == NULL) 00373 return 0; 00374 else 00375 return mLetter[i]->getWidth(); 00376 } 00377 00378 00379 void XFuPrinter::setLetterSpacing(INT32 aSpacing) 00380 { 00381 mLetterSpacing = aSpacing; 00382 } 00383 00384 00385 INT32 XFuPrinter::getLetterSpacing() 00386 { 00387 return mLetterSpacing; 00388 } 00389 00390 00391 void XFuPrinter::setLineSpacing(INT32 aSpacing) 00392 { 00393 mLineSpacing = aSpacing; 00394 } 00395 00396 00397 INT32 XFuPrinter::getLineSpacing() 00398 { 00399 return mLineSpacing; 00400 } 00401 00402 00403 INT32 XFuPrinter::getLineHeight() 00404 { 00405 return mLineHeight; 00406 } 00407 00408 00409 void XFuPrinter::setSpaceWidth(INT32 aSpacing) 00410 { 00411 mSpaceWidth = aSpacing; 00412 } 00413 00414 00415 XFuPrinter::~XFuPrinter() 00416 { 00417 int i; 00418 if (mLetter) 00419 { 00420 for (i = 0; i < mMaxletter; ++i) 00421 delete mLetter[i]; 00422 } 00423 delete[] mLetter; 00424 } 00425 00426 00427 XFuPrinter::XFuPrinter() 00428 { 00429 mLetter = NULL; 00430 }
![]() | ||||
![]() |
Confidential Copyright © 2002-2003 Fathammer | with doxygen by Dimitri van Heesch |